﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.IO;
using System.Collections.Generic;
using DirectorySynchronizer;

namespace DirSyncTests
{
    public class DirSyncTestException : Exception
    {
        public DirSyncTestException(string argMessage) : base(argMessage) { }
    }

    internal static class Comparers
    {
        static int unexpectedcomparisonresults = 0;
        /// <summary>
        /// Compare Directories and Contents
        /// </summary>
        /// <param name="argDirSyncOptions"></param>
        /// <param name="argExpectedValue"></param>
        /// <returns></returns>
        private static bool CDAC(DirSyncOptions argDirSyncOptions, bool? argExpectedValue)
        {
            string dirone = argDirSyncOptions.SourceDirectory;
            string dirtwo = argDirSyncOptions.TargetDirectory;
            bool returnvalue = false;
            if (!DirectoriesComparisonLooper(dirone, dirtwo, argDirSyncOptions.CopyAttributes)) { returnvalue = false; }
            else { returnvalue = DirectoriesComparisonLooper(dirtwo, dirone, argDirSyncOptions.CopyAttributes); }
            if (argExpectedValue != null && returnvalue != argExpectedValue)
            {
                unexpectedcomparisonresults++;
                Console.WriteLine("UNEXPECTED RETURN VALUE");
            }
            return returnvalue;
        }
        /// <summary>
        /// Compare Directories and Contents
        /// </summary>
        /// <param name="argDirOne"></param>
        /// <param name="argDirTwo"></param>
        /// <param name="argCheckAttributes"></param>
        /// <param name="argExpectedValue">pass null if calling from recursion chain</param>
        /// <returns></returns>
        private static bool CDAC(string argDirOne, string argDirTwo, bool argCheckAttributes, bool? argExpectedValue)
        {
            bool returnvalue = false;
            if (!DirectoriesComparisonLooper(argDirOne, argDirTwo, argCheckAttributes)) { returnvalue = false; }
            else { returnvalue = DirectoriesComparisonLooper(argDirTwo, argDirOne, argCheckAttributes); }
            if (argExpectedValue != null && returnvalue != argExpectedValue)
            {
                unexpectedcomparisonresults++;
                Console.WriteLine("UNEXPECTED RETURN VALUE:");
            }
            return returnvalue;
        }
        private static bool DirectoriesComparisonLooper(string argDirOne, string argDirTwo, bool argCheckAttributes)
        {
            foreach (string dir in Directory.GetDirectories(argDirOne))
            {
                string[] dirparts = dir.Split(Path.DirectorySeparatorChar);
                string equivalenttarget = Path.Combine(argDirTwo, dirparts[dirparts.Length - 1]);
                if (!Directory.Exists(equivalenttarget)) { return false; }
                if (!CDAC(dir, equivalenttarget, argCheckAttributes, null)) { return false; }
            }
            foreach (string file in Directory.GetFiles(argDirOne))
            {
                string[] dirparts = file.Split(Path.DirectorySeparatorChar);
                string equivalenttarget = Path.Combine(argDirTwo, dirparts[dirparts.Length - 1]);
                if (!File.Exists(equivalenttarget)) { return false; }
                FileInfo fione = new FileInfo(file);
                FileInfo fitwo = new FileInfo(equivalenttarget);
                if (fione.Length != fitwo.Length) { return false; }
                StreamReader srone = new StreamReader(file);
                StreamReader srtwo = new StreamReader(equivalenttarget);
                if (srone.ReadToEnd() != srtwo.ReadToEnd())
                {
                    srone.Close();
                    srtwo.Close();
                    return false;
                }
                srone.Close();
                srtwo.Close();
                if (argCheckAttributes)
                {
                    if (fione.Attributes != fitwo.Attributes) { return false; }
                    if (fione.CreationTime != fitwo.CreationTime) { return false; }
                    if (fione.LastAccessTime != fitwo.LastAccessTime) { return false; }
                    if (fione.LastWriteTime != fitwo.LastWriteTime) { return false; }
                }
            }
            return true;
        }

        /// <summary>
        /// Gets list of of files and subdirectories in each of two directories 
        /// that are not in the other directory.
        /// </summary>
        /// <param name="argDirSyncOptions"></param>
        /// <returns>array of filepath strings that are different between two directories</returns>
        internal static List<string> GetDiffList(DirSyncOptions argDirSyncOptions)
        {
            List<string> returnlist = new List<string>();
            GetDiffListRecurser(argDirSyncOptions.SourceDirectory, argDirSyncOptions.TargetDirectory, argDirSyncOptions.CopyAttributes, ref returnlist, "srce2targ");
            GetDiffListRecurser(argDirSyncOptions.TargetDirectory, argDirSyncOptions.SourceDirectory, argDirSyncOptions.CopyAttributes, ref returnlist, "targ2srce");
            return returnlist;
        }
        internal static List<string> GetDiffList(string argSourceDir, string argTargetDir, bool argCheckAttr)
        {
            List<string> returnlist = new List<string>();
            GetDiffListRecurser(argSourceDir, argTargetDir, argCheckAttr, ref returnlist, "srce2targ");
            GetDiffListRecurser(argTargetDir, argSourceDir, argCheckAttr, ref returnlist, "targ2srce");
            return returnlist;
        }
        private static void GetDiffListRecurser(string argSourceDir, string argTargetDir, bool argCheckAttr, ref List<string> argYieldList, string argDescriptionPrefix)
        {
            Dictionary<string, string> recursilist = new Dictionary<string, string>();
            foreach (string dir in Directory.GetDirectories(argSourceDir))
            {
                string[] dirparts = dir.Split(Path.DirectorySeparatorChar);
                string equivalenttarget = Path.Combine(argTargetDir, dirparts[dirparts.Length - 1]);
                if (!Directory.Exists(equivalenttarget)) { argYieldList.Add(argDescriptionPrefix + ":" + equivalenttarget); }
                else
                {
                    //if (argCheckAttr)
                    //{
                    //    DirectoryInfo dirinfo = new DirectoryInfo(dir);
                    //    DirectoryInfo equivalentinfo = new DirectoryInfo(equivalenttarget);
                    //    if (dirinfo.Attributes != equivalentinfo.Attributes ||
                    //        dirinfo.CreationTime != equivalentinfo.CreationTime ||
                    //        dirinfo.LastAccessTime != equivalentinfo.LastAccessTime ||
                    //        dirinfo.LastWriteTime != equivalentinfo.LastWriteTime)
                    //    {
                    //        argYieldList.Add(argDescriptionPrefix + ":" + equivalenttarget + ":attr");
                    //    }
                    //}
                    recursilist.Add(dir, equivalenttarget);
                }
            }
            foreach (string file in Directory.GetFiles(argSourceDir))
            {
                string[] dirparts = file.Split(Path.DirectorySeparatorChar);
                string equivalenttarget = Path.Combine(argTargetDir, dirparts[dirparts.Length - 1]);
                if (!File.Exists(equivalenttarget)) { argYieldList.Add(argDescriptionPrefix + ":" + equivalenttarget + ":missing"); }
                else
                {
                    FileInfo fione = new FileInfo(file);
                    FileInfo fitwo = new FileInfo(equivalenttarget);
                    if (fione.Length != fitwo.Length)
                    { argYieldList.Add(argDescriptionPrefix + ":" + equivalenttarget + ":length"); }
                    else
                    {
                        StreamReader srone = new StreamReader(file);
                        StreamReader srtwo = new StreamReader(equivalenttarget);
                        string fileonecontents = srone.ReadToEnd();
                        string filetwocontents = srtwo.ReadToEnd();
                        srone.Close();
                        srtwo.Close();
                        if (fileonecontents != filetwocontents)
                        { argYieldList.Add(argDescriptionPrefix + ":" + equivalenttarget + ":contents"); }
                    }

                    if (fione.Attributes != fitwo.Attributes) // || fione.CreationTime != fitwo.CreationTime
                    { argYieldList.Add(argDescriptionPrefix + ":" + equivalenttarget + ":attributes"); }

                    //if (fione.LastAccessTime != fitwo.LastAccessTime) //
                    //{ argYieldList.Add(argDescriptionPrefix + ":" + equivalenttarget + ":attributes"); }

                    //if (fione.LastWriteTime != fitwo.LastWriteTime)
                    //{ argYieldList.Add(argDescriptionPrefix + ":" + equivalenttarget + ":attributes"); continue; }
                }
            }
            foreach (string dir in recursilist.Keys)
            {
                GetDiffListRecurser(dir, recursilist[dir], argCheckAttr, ref argYieldList, argDescriptionPrefix);
            }
        }

        /// <summary>
        /// Gets count of differences between two string array difference lists.
        /// </summary>
        /// <param name="argDiffListOne"></param>
        /// <param name="argDiffListTwo"></param>
        /// <returns>difference count</returns>
        private static void DiffList(List<string> argDiffListOne, List<string> argDiffListTwo, ref List<string> argResultArray)
        {
            string[] listonearray = argDiffListOne.ToArray();
            string[] listtwoarray = argDiffListTwo.ToArray();
            bool matchfound = false;
            for (int iii = 0; iii < listonearray.Length; iii++)
            {
                matchfound = false;
                for (int jjj = 0; jjj < listtwoarray.Length; jjj++)
                {
                    if (listonearray[iii] == listtwoarray[jjj])
                    {
                        matchfound = true;
                        break;
                    }
                }
                if (!matchfound) { argResultArray.Add(listonearray[iii]); }
            }
        }
        public static int DiffListsDiffCount(List<string> argDiffListOne, List<string> argDiffListTwo)
        {
            List<string> returncounterarray = new List<string>();
            DiffList(argDiffListOne, argDiffListTwo, ref returncounterarray);
            DiffList(argDiffListTwo, argDiffListOne, ref returncounterarray);
            for (int iii = returncounterarray.Count - 1; iii >= 0; iii--)
            {
                for (int jjj = 0; jjj < returncounterarray.Count; jjj++)
                {
                    if (iii != jjj && returncounterarray[iii] == returncounterarray[jjj])
                    {
                        returncounterarray.RemoveAt(iii);
                        break;
                    }
                }
            }
            return returncounterarray.Count;
        }
    }


    [TestClass]
    public class DirSyncUnitTest
    {
        readonly internal static string sourcedir = @"C:\testingsource";
        readonly internal static string targetdir = @"C:\testingtarget";
        readonly internal static string subdir = "subdir";
        readonly internal static string fileonename = "fileone.txt";
        readonly internal static string filetwoname = "filetwo.txt";
        readonly internal static string fileonecontents = "file one contents";
        readonly internal static string filetwocontents = "file two contents";
        readonly internal static string additionaltext = " with additional text";
        int unexpectedtestresults = 0;
        DateTime moddatetime = DateTime.Now.AddYears(-1).AddMonths(-1).AddDays(-1).AddMinutes(-1).AddSeconds(-1);

        internal static void p(string argString)
        {
            Console.WriteLine(argString);
        }
        internal static void CreateInitialTestDirs()
        {
            string sourcesubdir = Path.Combine(sourcedir, subdir);
            if (!Directory.Exists(sourcesubdir)) { Directory.CreateDirectory(sourcesubdir); }
            if (!Directory.Exists(sourcedir)) { Directory.CreateDirectory(sourcedir); }
            if (!Directory.Exists(targetdir)) { Directory.CreateDirectory(targetdir); }
        }
        internal static void CreateInitialTestFiles()
        {
            p("Creating test directories in initialized state");
            string workfilefullname = Path.Combine(sourcedir, fileonename);
            if (!Directory.Exists(sourcedir) || !Directory.Exists(targetdir))
            { throw new DirSyncTestException("Expected test directory does not exist."); }
            if (!File.Exists(workfilefullname))
            {
                StreamWriter fileonesw = new StreamWriter(workfilefullname);
                fileonesw.WriteLine(fileonecontents);
                fileonesw.Close();
            }
            workfilefullname = Path.Combine(sourcedir, filetwoname);
            if (!File.Exists(workfilefullname))
            {
                StreamWriter filetwosw = new StreamWriter(workfilefullname);
                filetwosw.WriteLine(filetwocontents);
                filetwosw.Close();
            }
        }
        internal static void ModifyFileAttributes(string argFilename)
        {
            //File.SetCreationTime(argFilename, moddatetime);
            FileInfo fi = new FileInfo(argFilename);
            FileAttributes fa = fi.Attributes;
            if (fi.Attributes == FileAttributes.Archive)
            {
                fa = fi.Attributes & ~FileAttributes.Archive;
            }
            else
            {
                fa = fi.Attributes & FileAttributes.Archive;
            }
            File.SetAttributes(argFilename, fa);
        }
        private void ModifyFileContents(string argFilename)
        {
            if (!File.Exists(argFilename))
            {
                throw new DirSyncTestException("Unexpected missing file: '" + argFilename + "'");
            }
            StreamWriter fileonesw = new StreamWriter(argFilename, true);
            fileonesw.WriteLine(additionaltext);
            fileonesw.Close();
            p("modifing file: '" + argFilename + "'");
        }
        private void DeleteFile(string argFilename)
        {
            if (File.Exists(argFilename))
            {
                File.Delete(argFilename);
            }
            else
            {
                throw new DirSyncTestException("Unexpected file deletion of non-existent file attempt.");
            }
        }
        private void DeleteDirectory(string argDirname)
        {
            if (Directory.Exists(argDirname))
            {
                Directory.Delete(argDirname, true);
            }
            else
            {
                throw new DirSyncTestException("Unexpected directory deletion attempt of non-existent directory.");
            }
        }
        internal static void DeleteTestDirsAndFiles()
        {
            if (Directory.Exists(sourcedir)) { Directory.Delete(sourcedir, true); }
            if (Directory.Exists(targetdir)) { Directory.Delete(targetdir, true); }
        }
        private int AlertOnUnexpected(int argTestValue, int argExpectedValue)
        {
            if (argTestValue != argExpectedValue)
            {
                unexpectedtestresults++;
                p("UNEXPECTED RETURN VALUE:");
            }
            return argTestValue;
        }
        private bool AlertOnUnexpected(bool argTestValue, bool argExpectedValue)
        {
            if (argTestValue != argExpectedValue)
            {
                unexpectedtestresults++;
                p("UNEXPECTED RETURN VALUE:");
            }
            return argTestValue;
        }
        private bool QuickCheckSmallFileContents(string argFilename, string argContents)
        {
            if (!File.Exists(argFilename))
            {
                return false;
            }
            StreamReader sr = new StreamReader(argFilename);
            if (sr.ReadToEnd() == argContents)
            {
                return true;
            }
            return false;
        }
        private DummyIProgressDisplay dipd = new DummyIProgressDisplay();

        [TestMethod]
        public void Test1p1Method()
        {
            DirSyncOptions dso = new DirSyncOptions();
            dso.CopyAttributes = false;
            dso.IgnoreOverwriteAndDelete = false;
            dso.PreviewOnly = true;
            dso.SourceDirectory = sourcedir;
            dso.SuppressDataGridResultsDisplay = false;
            dso.TagCopyNotOldFile = false;
            dso.TagInsteadOfDelete = false;
            dso.TagInsteadOfOverwrite = false;
            dso.TargetDirectory = targetdir;
            DirSynchronizer ds = new DirSynchronizer(dso, dipd);
            int[] expecteddiffdiffs = { 0, //Add Directory and Files
                                       0, //Change File Contents
                                       0, //Change File Attributes
                                       0, //Delete File
                                       0, //Rename Directory
                                       0 }; //Delete Directory
            TestScenarioArrangeActAssertRunner(dso, expecteddiffdiffs);
        }
        [TestMethod]
        public void Test1p2Method()
        {
            Console.WriteLine("no changes should be synchronized with these settings, individual change scenarios tautological with 1.1");
        }
        [TestMethod]
        public void Test1p3Method()
        {
            DirSyncOptions dso = new DirSyncOptions();
            dso.CopyAttributes = false;
            dso.IgnoreOverwriteAndDelete = false;
            dso.PreviewOnly = false;
            dso.SourceDirectory = sourcedir;
            dso.SuppressDataGridResultsDisplay = false;
            dso.TagCopyNotOldFile = false;
            dso.TagInsteadOfDelete = false;
            dso.TagInsteadOfOverwrite = false;
            dso.TargetDirectory = targetdir;
            int[] expecteddiffdiffs = { 3, //Add Directory and Files
                                       2, //Change File Contents
                                       0, //Change File Attributes
                                       1, //Delete File
                                       2, //Rename Directory
                                       1 }; //Delete Directory
            TestScenarioArrangeActAssertRunner(dso, expecteddiffdiffs);
        }
        [TestMethod]
        public void Test1p4Method()
        {
            DirSyncOptions dso = new DirSyncOptions();
            dso.CopyAttributes = true;
            dso.IgnoreOverwriteAndDelete = false;
            dso.PreviewOnly = false;
            dso.SourceDirectory = sourcedir;
            dso.SuppressDataGridResultsDisplay = false;
            dso.TagCopyNotOldFile = false;
            dso.TagInsteadOfDelete = false;
            dso.TagInsteadOfOverwrite = false;
            dso.TargetDirectory = targetdir;
            int[] expecteddiffdiffs = { 3, //Add Directory and Files
                                       2, //Change File Contents
                                       2, //Change File Attributes
                                       1, //Delete File
                                       2, //Rename Directory
                                       1 }; //Delete Directory
            TestScenarioArrangeActAssertRunner(dso, expecteddiffdiffs);
        }

        [TestMethod]
        public void Test2p1Method()
        {
            Console.WriteLine("test basically the same as 1.3");
        }
        [TestMethod]
        public void Test2p2Method()
        {
            Console.WriteLine("test basically the same as 1.4");
        }
        [TestMethod]
        public void Test2p3Method()
        {
            DirSyncOptions dso = new DirSyncOptions();
            dso.CopyAttributes = false;
            dso.IgnoreOverwriteAndDelete = true;
            dso.PreviewOnly = false;
            dso.SourceDirectory = sourcedir;
            dso.SuppressDataGridResultsDisplay = false;
            dso.TagCopyNotOldFile = false;
            dso.TagInsteadOfDelete = false;
            dso.TagInsteadOfOverwrite = false;
            dso.TargetDirectory = targetdir;
            int[] expecteddiffdiffs = { 3, //Add Directory and Files
                                       0, //Change File Contents
                                       0, //Change File Attributes
                                       0, //Delete File
                                       1, //Rename Directory
                                       0 }; //Delete Directory
            TestScenarioArrangeActAssertRunner(dso, expecteddiffdiffs);
        }
        [TestMethod]
        public void Test2p4Method()
        {
            DirSyncOptions dso = new DirSyncOptions();
            dso.CopyAttributes = true;
            dso.IgnoreOverwriteAndDelete = true;
            dso.PreviewOnly = false;
            dso.SourceDirectory = sourcedir;
            dso.SuppressDataGridResultsDisplay = false;
            dso.TagCopyNotOldFile = false;
            dso.TagInsteadOfDelete = false;
            dso.TagInsteadOfOverwrite = false;
            dso.TargetDirectory = targetdir;
            int[] expecteddiffdiffs = { 3, //Add Directory and Files
                                       0, //Change File Contents
                                       2, //Change File Attributes
                                       0, //Delete File
                                       1, //Rename Directory
                                       0 }; //Delete Directory
            TestScenarioArrangeActAssertRunner(dso, expecteddiffdiffs);
        }

        [TestMethod]
        public void Test3p1Method()
        {
            Console.WriteLine("Identical to 1.3 and 2.1, additional test run not required.");
        }
        [TestMethod]
        public void Test3p2Method()
        {
            Console.WriteLine("Identical to 1.4 and 2.2, additional test run not required.");
        }
        [TestMethod]
        public void Test3p3Method()
        {
            DirSyncOptions dso = new DirSyncOptions();
            dso.CopyAttributes = true;
            dso.IgnoreOverwriteAndDelete = false;
            dso.PreviewOnly = false;
            dso.SourceDirectory = sourcedir;
            dso.SuppressDataGridResultsDisplay = false;
            dso.TagCopyNotOldFile = true;
            dso.TagInsteadOfDelete = false;
            dso.TagInsteadOfOverwrite = false;
            dso.TargetDirectory = targetdir;
            int[] expecteddiffdiffs = { 3, //Add Directory and Files
                                       2, //Change File Contents
                                       2, //Change File Attributes
                                       1, //Delete File
                                       2, //Rename Directory
                                       1 }; //Delete Directory
            TestScenarioArrangeActAssertRunner(dso, expecteddiffdiffs);
        }
        [TestMethod]
        public void Test3p4Method()
        {
            DirSyncOptions dso = new DirSyncOptions();
            dso.CopyAttributes = false;
            dso.IgnoreOverwriteAndDelete = false;
            dso.PreviewOnly = false;
            dso.SourceDirectory = sourcedir;
            dso.SuppressDataGridResultsDisplay = false;
            dso.TagCopyNotOldFile = true;
            dso.TagInsteadOfDelete = false;
            dso.TagInsteadOfOverwrite = false;
            dso.TargetDirectory = targetdir;
            int[] expecteddiffdiffs = { 3, //Add Directory and Files
                                       2, //Change File Contents
                                       0, //Change File Attributes
                                       1, //Delete File
                                       2, //Rename Directory
                                       1 }; //Delete Directory
            TestScenarioArrangeActAssertRunner(dso, expecteddiffdiffs);
        }

        [TestMethod]
        public void Test4p1Method()
        {
            DirSyncOptions dso = new DirSyncOptions();
            dso.CopyAttributes = false;
            dso.IgnoreOverwriteAndDelete = false;
            dso.PreviewOnly = false;
            dso.SourceDirectory = sourcedir;
            dso.SuppressDataGridResultsDisplay = false;
            dso.TagCopyNotOldFile = false;
            dso.TagInsteadOfDelete = false;
            dso.TagInsteadOfOverwrite = true;
            dso.TargetDirectory = targetdir;
            int[] expecteddiffdiffs = { 3, //Add Directory and Files
                                       3, //Change File Contents
                                       1, //Change File Attributes
                                       1, //Delete File
                                       2, //Rename Directory
                                       1 }; //Delete Directory
            TestScenarioArrangeActAssertRunner(dso, expecteddiffdiffs);
        }
        [TestMethod]
        public void Test4p2Method()
        {
            DirSyncOptions dso = new DirSyncOptions();
            dso.CopyAttributes = true;
            dso.IgnoreOverwriteAndDelete = false;
            dso.PreviewOnly = false;
            dso.SourceDirectory = sourcedir;
            dso.SuppressDataGridResultsDisplay = false;
            dso.TagCopyNotOldFile = false;
            dso.TagInsteadOfDelete = false;
            dso.TagInsteadOfOverwrite = true;
            dso.TargetDirectory = targetdir;
            int[] expecteddiffdiffs = { 3, //Add Directory and Files
                                       3, //Change File Contents
                                       3, //Change File Attributes
                                       1, //Delete File
                                       2, //Rename Directory
                                       1 }; //Delete Directory
            TestScenarioArrangeActAssertRunner(dso, expecteddiffdiffs);
        }
        [TestMethod]
        public void Test4p3Method()
        {
            DirSyncOptions dso = new DirSyncOptions();
            dso.CopyAttributes = false;
            dso.IgnoreOverwriteAndDelete = false;
            dso.PreviewOnly = false;
            dso.SourceDirectory = sourcedir;
            dso.SuppressDataGridResultsDisplay = false;
            dso.TagCopyNotOldFile = true;
            dso.TagInsteadOfDelete = false;
            dso.TagInsteadOfOverwrite = true;
            dso.TargetDirectory = targetdir;
            int[] expecteddiffdiffs = { 3, //Add Directory and Files
                                       1, //Change File Contents
                                       0, //Change File Attributes
                                       2, //Delete File
                                       2, //Rename Directory
                                       1 }; //Delete Directory
            TestScenarioArrangeActAssertRunner(dso, expecteddiffdiffs);
        }
        [TestMethod]
        public void Test4p4Method()
        {
            DirSyncOptions dso = new DirSyncOptions();
            dso.CopyAttributes = true;
            dso.IgnoreOverwriteAndDelete = false;
            dso.PreviewOnly = false;
            dso.SourceDirectory = sourcedir;
            dso.SuppressDataGridResultsDisplay = false;
            dso.TagCopyNotOldFile = true;
            dso.TagInsteadOfDelete = true;
            dso.TagInsteadOfOverwrite = true;
            dso.TargetDirectory = targetdir;
            int[] expecteddiffdiffs = { 3, //Add Directory and Files
                                       1, //Change File Contents
                                       1, //Change File Attributes
                                       6, //Delete File
                                       9, //Rename Directory
                                       10 }; //Delete Directory
            TestScenarioArrangeActAssertRunner(dso, expecteddiffdiffs);
        }

        [TestMethod]
        public void Test5p1Method()
        {
            DirSyncOptions dso = new DirSyncOptions();
            dso.CopyAttributes = false;
            dso.IgnoreOverwriteAndDelete = false;
            dso.PreviewOnly = false;
            dso.SourceDirectory = sourcedir;
            dso.SuppressDataGridResultsDisplay = false;
            dso.TagCopyNotOldFile = false;
            dso.TagInsteadOfDelete = true;
            dso.TagInsteadOfOverwrite = true;
            dso.TargetDirectory = targetdir;
            int[] expecteddiffdiffs = { 3, //Add Directory and Files
                                       3, //Change File Contents
                                       2, //Change File Attributes
                                       4, //Delete File
                                       7, //Rename Directory
                                       8 }; //Delete Directory
            TestScenarioArrangeActAssertRunner(dso, expecteddiffdiffs);
        }
        [TestMethod]
        public void Test5p2Method()
        {
            DirSyncOptions dso = new DirSyncOptions();
            dso.CopyAttributes = true;
            dso.IgnoreOverwriteAndDelete = false;
            dso.PreviewOnly = false;
            dso.SourceDirectory = sourcedir;
            dso.SuppressDataGridResultsDisplay = false;
            dso.TagCopyNotOldFile = false;
            dso.TagInsteadOfDelete = true;
            dso.TagInsteadOfOverwrite = true;
            dso.TargetDirectory = targetdir;
            int[] expecteddiffdiffs = { 3, //Add Directory and Files
                                       3, //Change File Contents
                                       4, //Change File Attributes
                                       4, //Delete File
                                       7, //Rename Directory
                                       8 }; //Delete Directory
            TestScenarioArrangeActAssertRunner(dso, expecteddiffdiffs);
        }
        [TestMethod]
        public void Test5p3Method()
        {
            DirSyncOptions dso = new DirSyncOptions();
            dso.CopyAttributes = true;
            dso.IgnoreOverwriteAndDelete = false;
            dso.PreviewOnly = false;
            dso.SourceDirectory = sourcedir;
            dso.SuppressDataGridResultsDisplay = false;
            dso.TagCopyNotOldFile = true;
            dso.TagInsteadOfDelete = true;
            dso.TagInsteadOfOverwrite = true;
            dso.TargetDirectory = targetdir;
            int[] expecteddiffdiffs = { 3, //Add Directory and Files
                                       1, //Change File Contents
                                       1, //Change File Attributes
                                       6, //Delete File
                                       9, //Rename Directory
                                       10 }; //Delete Directory
            TestScenarioArrangeActAssertRunner(dso, expecteddiffdiffs);
        }
        [TestMethod]
        public void Test5p4Method()
        {
            DirSyncOptions dso = new DirSyncOptions();
            dso.CopyAttributes = true;
            dso.IgnoreOverwriteAndDelete = false;
            dso.PreviewOnly = false;
            dso.SourceDirectory = sourcedir;
            dso.SuppressDataGridResultsDisplay = false;
            dso.TagCopyNotOldFile = true;
            dso.TagInsteadOfDelete = true;
            dso.TagInsteadOfOverwrite = true;
            dso.TargetDirectory = targetdir;
            int[] expecteddiffdiffs = { 3, //Add Directory and Files
                                       1, //Change File Contents
                                       1, //Change File Attributes
                                       6, //Delete File
                                       9, //Rename Directory
                                       10 }; //Delete Directory
            TestScenarioArrangeActAssertRunner(dso, expecteddiffdiffs);
        }


        private void TestScenarioArrangeActAssertRunner(DirSyncOptions argDso, int[] argExpectedDiffs)
        {
            int aEDindex = 0;

            DeleteTestDirsAndFiles();
            CreateInitialTestDirs();
            CreateInitialTestFiles();
            //Add Directory, Add File
            DirSynchronizer ds = new DirSynchronizer(argDso, dipd);
            List<string> presyncdiff = Comparers.GetDiffList(argDso);
            ds.StartDirectorySynchronization();
            List<string> postsyncdiff = Comparers.GetDiffList(argDso);
            int expecteddiffdiff = argExpectedDiffs[aEDindex++];
            int actualdiffdiff = Comparers.DiffListsDiffCount(presyncdiff, postsyncdiff);
            Assert.AreEqual(expecteddiffdiff, actualdiffdiff);

            //Change File Contents
            ModifyFileContents(Path.Combine(sourcedir, fileonename));
            presyncdiff = Comparers.GetDiffList(argDso);
            ds = new DirSynchronizer(argDso, dipd);
            ds.StartDirectorySynchronization();
            postsyncdiff = Comparers.GetDiffList(argDso);
            expecteddiffdiff = argExpectedDiffs[aEDindex++];
            actualdiffdiff = Comparers.DiffListsDiffCount(presyncdiff, postsyncdiff);
            Assert.AreEqual(expecteddiffdiff, actualdiffdiff);

            //Change File Attributes
            ModifyFileAttributes(Path.Combine(sourcedir, fileonename));
            presyncdiff = Comparers.GetDiffList(argDso);
            ds = new DirSynchronizer(argDso, dipd);
            ds.StartDirectorySynchronization();
            postsyncdiff = Comparers.GetDiffList(argDso);
            expecteddiffdiff = argExpectedDiffs[aEDindex++];
            actualdiffdiff = Comparers.DiffListsDiffCount(presyncdiff, postsyncdiff);
            Assert.AreEqual(expecteddiffdiff, actualdiffdiff);

            //Delete File
            DeleteFile(Path.Combine(sourcedir, fileonename));
            presyncdiff = Comparers.GetDiffList(argDso);
            ds = new DirSynchronizer(argDso, dipd);
            ds.StartDirectorySynchronization();
            postsyncdiff = Comparers.GetDiffList(argDso);
            expecteddiffdiff = argExpectedDiffs[aEDindex++];
            actualdiffdiff = Comparers.DiffListsDiffCount(presyncdiff, postsyncdiff);
            Assert.AreEqual(expecteddiffdiff, actualdiffdiff);

            //Rename Directory
            string newdirname = Path.Combine(sourcedir, subdir + "renamed");
            Directory.Move(Path.Combine(sourcedir, subdir), newdirname);
            presyncdiff = Comparers.GetDiffList(argDso);
            ds = new DirSynchronizer(argDso, dipd);
            ds.StartDirectorySynchronization();
            postsyncdiff = Comparers.GetDiffList(argDso);
            expecteddiffdiff = argExpectedDiffs[aEDindex++];
            actualdiffdiff = Comparers.DiffListsDiffCount(presyncdiff, postsyncdiff);
            Assert.AreEqual(expecteddiffdiff, actualdiffdiff);

            //Delete Directory
            DeleteDirectory(newdirname);
            presyncdiff = Comparers.GetDiffList(argDso);
            ds = new DirSynchronizer(argDso, dipd);
            ds.StartDirectorySynchronization();
            postsyncdiff = Comparers.GetDiffList(argDso);
            expecteddiffdiff = argExpectedDiffs[aEDindex++];
            actualdiffdiff = Comparers.DiffListsDiffCount(presyncdiff, postsyncdiff);
            Assert.AreEqual(expecteddiffdiff, actualdiffdiff);
        }
    }
}
